function GenerateCases(handles)
% This file is part of CISNE.
%
%     CISNE is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     any later version.
%
%     CISNE is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with CISNE.  If not, see <http://www.gnu.org/licenses/>.

% Copyright 2011. Jose Maria Garcia-Valdecasas Bernal

% 21-Oct-09 ver. 1.0 (splitted from CISNE.m).
% 24-Jun-11 ver. 1.1 (updated to work with New UX).


%%first of all check if all needed input data is correct.
% TODO: rewrite validateinput function.

%if everything is ok, let's generate SWN files.

%Project and Start-up data
Name=handles.SetupWidget.getValue('Project Name');
Name=regexprep(Name,'\s+','_');
nRun=handles.SetupWidget.getValue('Initial Case');
projectPath=char(handles.SetupWidget.getValue('Project Folder'));
if isempty(projectPath)
    projectPath=pwd; %if empty, current path is project path.
end

%depmin=handles.SetupWidget.getValue('Minimum Depth');

%Model definition data
DirMode=char(handles.SetupWidget.getValue('Spectral dir'));
minDir=handles.SetupWidget.getValue('Spectral dir.Min dir');
maxDir=handles.SetupWidget.getValue('Spectral dir.Max dir');
ndirs=handles.SetupWidget.getValue('Spt dir mesh');
frmin=handles.SetupWidget.getValue('Spt min frequency');
frmax=handles.SetupWidget.getValue('Spt max frequency');
nfrec=handles.SetupWidget.getValue('Spt frequencies');
CWind=handles.SetupWidget.getValue('Constant Wind');
WindVel=handles.SetupWidget.getValue('Constant Wind.Wind velocity');
WindAngle=handles.SetupWidget.getValue('Constant Wind.Wind direction');

%Boundary conditions
spt=char(handles.SetupWidget.getValue('Spectra shape'));
switch spt
    case 'JONSWAP'
        sptParam=handles.SetupWidget.getValue('Spectra shape.Gamma parameter');
    case 'GAUSS'
        sptParam=handles.SetupWidget.getValue('Spectra shape.Sigfr parameter');
    otherwise
        sptParam=[];
end
Period=char(handles.SetupWidget.getValue('Wave period'));
DSPRMod=char(handles.SetupWidget.getValue('Directional width'));
DSPR=handles.SetupWidget.getValue('Dir spreading');

%Physics
GenMode=char(handles.SetupWidget.getValue('Generation mode'));
Quad=handles.SetupWidget.getValue('Quadrupet');
Triad=handles.SetupWidget.getValue('Triad');
Breaking=handles.SetupWidget.getValue('Wave breaking');
brAlpha=handles.SetupWidget.getValue('Wave breaking.Dissipation rate');
brGamma=handles.SetupWidget.getValue('Wave breaking.Height vs depth ratio');
WCap=handles.SetupWidget.getValue('Whitecapping');
Friction=char(handles.SetupWidget.getValue('Friction'));


%Output locations, Generation Cases, Computational Grids...
Points=handles.TreeWidget.getControlPoints();
CaseList=get(handles.LW_Cases,'String');
CGrids=handles.TreeWidget.getCompGrids();
IGrids=handles.TreeWidget.getInputGrids();
OutputData=get(handles.TW_Output,'Data');
tmp=cell2mat(OutputData(:,2));
aux=OutputData(tmp,1);
OutputData=sprintf('%s ',aux{:});
clear tmp aux;

%path for input and output files
swndir=[projectPath filesep 'SWN'];
outdir=[projectPath filesep 'OUT'];
if ~isdir(swndir)
    mkdir(swndir);
end
if ~isdir(outdir)
    mkdir(outdir);
end

GridList=fieldnames(CGrids);
IGridList=fieldnames(IGrids);

%generate file with grid data (to be used with Draw Mesh functions)
fNameGrid=fullfile(outdir,[Name '.cgl']);
handles.TreeWidget.saveCGridList(fNameGrid);

%initiate progressbar for generation.
warning('off','MATLAB:hg:JavaSetHGPropertyParamValue');
set(handles.jProgressBar,'StringPainted','on','Maximum',length(CaseList),...
    'Value',0);
handles.jStatusBar.setText('Generating SWAN files, please wait.');

for j=1:size(CaseList)
    subrun=1;
    line=CaseList{j};
    [hs,tp,d,lvl,genside]=readCase(line);
    for k=1:length(GridList)
        fullname=sprintf('%02d-%s%03d-H%gT%gD%gLvl%g',subrun,Name,nRun+j-1,...
            hs,tp,d,lvl);
        subrun=subrun+1; %update subrun. One for each grid!
        fullname=regexprep(fullname,'\.','_');
        fname=[swndir filesep fullname '.swn'];
        fh1=fopen(fname,'w');
        
        %print header for SWAN files
        swanprint(fh1,'$>Input file for SWAN model\n');
        swanprint(fh1,'$>Generated by CISNE %s\n',handles.CISNE_VERSION);
        swanprint(fh1,'$>Copyright 2011,Jose Maria Garcia-Valdecasas Bernal\n');
        %print data for SWAN files using data from CISNE GUI.
        swanprint(fh1,'PROJECT \''%s\'' \''%03d\'' \n',Name,j);
        %TODO: add options to SET command!
        swanprint(fh1,'SET LEVEL %g NAUTICAL\n',lvl);
        swanprint(fh1,'MODE TWODIMENSIONAL\n');
        
        
        %get data needed for Computational Grid definition.
        X0=CGrids.(GridList{k}).X0;
        Y0=CGrids.(GridList{k}).Y0;
        Angle=CGrids.(GridList{k}).Angle;
        XLength=CGrids.(GridList{k}).XLength;
        YLength=CGrids.(GridList{k}).YLength;
        NX=XLength/CGrids.(GridList{k}).DX;
        NY=YLength/CGrids.(GridList{k}).DY;
        
        if strcmp(DirMode,'CIRCLE')
            swanprint(fh1,...
                'CGRID %9.7g %9.7g %g %9.7g %9.7g %i %i CIRCLE %i %g %g %i\n',...
                X0,Y0,Angle,XLength,YLength,NX,NY,ndirs,frmin,frmax,nfrec-1);
        else
            swanprint(fh1,...
                'CGRID %9.7g %9.7g %g %9.7g %9.7g %i %i SECTOR %g %g %i %g %g %i\n',...
                X0,Y0,Angle,XLength,YLength,NX,NY,minDir,maxDir,ndirs,...
                frmin,frmax,nfrec-1);
        end
        
        %write code for input grids.
        for l=1:length(IGridList)
            switch IGridList{l}
                case 'BATHYMETRY'
                swanprint(fh1,'INPGRID BOTTOM %9.7g %9.7g %g %i %i %i %i\n',...
                    IGrids.(IGridList{l}).X0,IGrids.(IGridList{l}).Y0,...
                    IGrids.(IGridList{l}).Angle,IGrids.(IGridList{l}).NX-1,...
                    IGrids.(IGridList{l}).NY-1,IGrids.(IGridList{l}).DX,...
                    IGrids.(IGridList{l}).DY);
                swanprint(fh1,'READINP BOTTOM %g \''%s\'' %i %i\n',...
                    IGrids.(IGridList{l}).Swap,IGrids.(IGridList{l}).File,...
                    IGrids.(IGridList{l}).Filetype,...
                    IGrids.(IGridList{l}).Header);
                case 'WIND'
                swanprint(fh1,'INPGRID WIND %9.7g %9.7g %g %i %i %i %i\n',...
                    IGrids.(IGridList{l}).X0,IGrids.(IGridList{l}).Y0,...
                    IGrids.(IGridList{l}).Angle,IGrids.(IGridList{l}).NX-1,...
                    IGrids.(IGridList{l}).NY-1,IGrids.(IGridList{l}).DX,...
                    IGrids.(IGridList{l}).DY);
                swanprint(fh1,'READINP WIND %g \''%s\'' %i %i\n',...
                    IGrids.(IGridList{l}).Swap,IGrids.(IGridList{l}).File,...
                    IGrids.(IGridList{l}).Filetype,...
                    IGrids.(IGridList{l}).header);
                case 'VEGETATION'
                swanprint(fh1,'INPGRID NPLANTS %9.7g %9.7g %g %i %i %i %i\n',...
                    IGrids.(IGridList{l}).X0,IGrids.(IGridList{l}).Y0,...
                    IGrids.(IGridList{l}).Angle,IGrids.(IGridList{l}).NX-1,...
                    IGrids.(IGridList{l}).NY-1,IGrids.(IGridList{l}).DX,...
                    IGrids.(IGridList{l}).DY);
                swanprint(fh1,'READINP NPLANTS %g \''%s\'' %i %i\n',...
                    IGrids.(IGridList{l}).Swap,IGrids.(IGridList{l}).File,...
                    IGrids.(IGridList{l}).Filetype,...
                    IGrids.(IGridList{l}).header);                    
                case 'CURRENT'
                swanprint(fh1,'INPGRID CURRENT %9.7g %9.7g %g %i %i %i %i\n',...
                    IGrids.(IGridList{l}).X0,IGrids.(IGridList{l}).Y0,...
                    IGrids.(IGridList{l}).Angle,IGrids.(IGridList{l}).NX-1,...
                    IGrids.(IGridList{l}).NY-1,IGrids.(IGridList{l}).DX,...
                    IGrids.(IGridList{l}).DY);
                swanprint(fh1,'READINP CURRENT %g \''%s\'' %i %i\n',...
                    IGrids.(IGridList{l}).Swap,IGrids.(IGridList{l}).File,...
                    IGrids.(IGridList{l}).Filetype,...
                    IGrids.(IGridList{l}).header);
                case 'FRICTION'
                swanprint(fh1,'INPGRID FRICTION %9.7g %9.7g %g %i %i %i %i\n',...
                    IGrids.(IGridList{l}).X0,IGrids.(IGridList{l}).Y0,...
                    IGrids.(IGridList{l}).Angle,IGrids.(IGridList{l}).NX-1,...
                    IGrids.(IGridList{l}).NY-1,IGrids.(IGridList{l}).DX,...
                    IGrids.(IGridList{l}).DY);
                swanprint(fh1,'READINP FRICTION %g \''%s\'' %i %i\n',...
                    IGrids.(IGridList{l}).Swap,IGrids.(IGridList{l}).File,...
                    IGrids.(IGridList{l}).Filetype,...
                    IGrids.(IGridList{l}).header);    
            end
        end
        if ~any(strcmp('WIND',IGridList))
            if CWind
                swanprint(fh1,'WIND %g %g\n',WindVel,WindAngle);
            end
        end
        %spectrum shape at boundary
        swanprint(fh1,'BOUN SHAPESPEC %s %g %s DSPR %s\n',spt,...
            sptParam,Period,DSPRMod);
        %Check if computational grid is nested or not.
        if isempty(CGrids.(GridList{k}).parent)
        
            for l=1:length(genside)
            swanprint(fh1,'BOUN SIDE %s CONSTANT PAR %g %g %g %g\n',...
                genside{l},hs,tp,d,DSPR);
            end
        else
            parent=CGrids.(GridList{k}).parent;
            Pos=find(strcmp(parent,GridList));
            child=find(strcmp(GridList{k},CGrids.(parent).nested));
            pName=sprintf('%02d-%s%03d-H%gT%gD%gLvl%g-%d',Pos,Name,nRun+j-1,...
            hs,tp,d,lvl,child);
            pName=regexprep(pName,'\.','_');
            swanprint(fh1,'BOUN NEST \''%s.NST\'' CLOSED\n',...
                fullfile(outdir,pName));
        end
        %physics
        switch GenMode
            case 'GEN3'
                swanprint(fh1,'GEN3 KOMEN\n');
            case 'GEN2'
                swanprint(fh1,'GEN2\n');
            case 'GEN1'
                swanprint(fh1,'GEN1\n');
        end
        
        if ~Quad
            swanprint(fh1,'OFF QUAD\n');
        end
        if Triad
            swanprint(fh1,'TRIAD\n');
        end
        if ~Breaking
            swanprint(fh1,'OFF BREAKING\n');
        else
            swanprint(fh1,'BREAKING CONSTANT %g %g\n',brAlpha,brGamma);
        end
        if ~WCap
            swanprint(fh1,'OFF WCAP\n');
        end
        switch Friction
            case 'JONSWAP'
                swanprint(fh1,'FRICTION JON 0.067\n');
            case 'COLLINS'
                swanprint(fh1,'FRICTION COLL 0.015\n');
            case 'MADSEN'
                swanprint(fh1,'FRICTION MAD 0.05\n');
        end
            
        %TODO: Add difraction and other settings!!
        vPoints=checkPoints(X0,Y0,XLength,YLength,Angle,Points);
        if size(vPoints,1)>0
            swanprint(fh1,'POINTS \''CPOINTS\'' %9.7g %9.7g &\n',...
                vPoints(1,1),vPoints(1,2));
            
            if size(vPoints,1)>1
                for l=2:size(vPoints,1)
                    swanprint(fh1,'%9.7g %9.7g &\n',...
                        vPoints(l,1),vPoints(l,2));
                end
            end
            
            swanprint(fh1,'SPECOUT \''CPOINTS\'' SPEC2D RELATIVE \''%s.SPC\''\n',...
                fullfile(outdir,fullname));
        end
        
        swanprint(fh1,'TABLE \''COMPGRID\'' HEADER \''%s.tbl\'' %s \n',...
            fullfile(outdir,fullname),OutputData);
        
        %check if current grid has nested grids to output needed data
        if ~isempty(CGrids.(GridList{k}).nested)
            for l=1:length(CGrids.(GridList{k}).nested)
                nName=CGrids.(GridList{k}).nested{l};
                swanprint(fh1,'NGRID \''%s\'' %g %g %g %g %g %i %i\n',...
                    nName,CGrids.(nName).X0,CGrids.(nName).Y0,...
                    CGrids.(nName).Angle,CGrids.(nName).XLength,...
                    CGrids.(nName).YLength,CGrids.(nName).NX,...
                    CGrids.(nName).NY);
                swanprint(fh1,'NESTOUT \''%s\'' \''%s-%d.NST\''\n',...
                	nName,fullfile(outdir,fullname),l);
            end
        end
        swanprint(fh1,'COMPUTE\n');
        swanprint(fh1,'STOP\n');
        
        fclose(fh1);
        
    end
    handles.jProgressBar.setValue(j);
end

handles.jProgressBar.setVisible(0);
handles.jStatusBar.setText('SWN FILES GENERATED.');

end

function swanprint(fh,varargin)

line=sprintf(varargin{1},varargin{2:end});
lSize= length(line);

if(lSize>120)
    %swan doesn't allow lines longer than 120 chars, split it
    lines=linewrap(line,110);
    
    for n=1:length(lines)-1
        fprintf(fh,'%s &\n',lines{n});
    end
    fprintf(fh,'%s\n',lines{n+1});
else
    fprintf(fh,'%s',line);
end
end


function vPoints=checkPoints(x0,y0,lx,ly,th,Points)

if ~isempty(Points)
if(tand(th)~=0)
    x1=x0+lx*cosd(th);
    x2=x1-ly*sind(th);
    x3=x2-lx*cosd(th);
    
    y1=y0+lx*sind(th);
    y2=y1+ly*cosd(th);
    y3=y2-lx*sind(th);
else
    x1=x0+lx;
    x2=x1;
    x3=x0;
    y1=y0;
    y2=y0+ly;
    y3=y2;
    
end
x=[x0 x1 x2 x3];
y=[y0 y1 y2 y3];

IN=inpolygon(Points(:,1),Points(:,2),x,y);
vPoints=Points(IN,:);
else
    vPoints=[];
end
end

function c = linewrap(s, maxchars)
%LINEWRAP Separate a single string into multiple strings
% Steven L. Eddins
% $Revision: 1.7 $  $Date: 2006/02/08 16:54:51 $

error(nargchk(1, 2, nargin));

bad_s = ~ischar(s) || (ndims(s) > 2) || (size(s, 1) ~= 1);
if bad_s
    error('S must be a single-row char array.');
end

if nargin < 2
    % Default value for second input argument.
    maxchars = 80;
end

% Trim leading and trailing whitespace.
s = strtrim(s);

% Form the desired regular expression from maxchars.
exp = sprintf('(\\S\\S{%d,}|.{1,%d})(?:\\s+|$)', maxchars, maxchars);

% Interpretation of regular expression (for maxchars = 80):
% '(\\S\\S{80,}|.{1,80})(?:\\s+|$)'
%
% Match either a non-whitespace character followed by 80 or more
% non-whitespace characters, OR any sequence of between 1 and 80
% characters; all followed by either one or more whitespace characters OR
% end-of-line.

tokens = regexp(s, exp, 'tokens').';

% Each element if the cell array tokens is single-element cell array
% containing a string.  Convert this to a cell array of strings.
get_contents = @(f) f{1};
c = cellfun(get_contents, tokens, 'UniformOutput', false);

% Remove trailing whitespace characters from strings in c.  This can happen
% if multiple whitespace characters separated the last word on a line from
% the first word on the following line.
c = deblank(c);
end


function [hs,tp,d,lvl,genside]=readCase(line)
    elem=regexp(line,'\s+','split');
    nelem=length(elem);
    genside=cell(1,nelem-4);
    for j=1:nelem-4 %si nelem=5 -> j=1:1 (solo 1 side) || nelem=7 -> 3 side
        genside{j}=elem{j};
    end
    hs=sscanf(elem{j+1},'%f');
    tp=sscanf(elem{j+2},'%f');
    d=sscanf(elem{j+3},'%f');
    lvl=sscanf(elem{j+4},'%f');
end